/* 
 * File:   MundoSBS.cpp
 * Author: paula
 * 
 * Created on 13 de octubre de 2014, 15:10
 */

#include <vector>

#include "MundoSBS.h"

MundoSBS::MundoSBS() {
    this->endMain = false;
    this->reloadLevelOne = false;
    this->salioManualmente = false;
    this->gameOver = false;
    //    this->gRenderer = NULL;
    this->waitingForReload = false;
    this->isObserver = false;
}

MundoSBS::MundoSBS(const MundoSBS& orig) {
}

MundoSBS::~MundoSBS() {
}

//Labels objects
Label* labelIP = new Label();
Label* inputIP = new Label();

Label* labelPuerto = new Label();
Label* inputPuerto = new Label();

Label* labelUsuario = new Label();
Label* inputUsuario = new Label();

Label* errorLabel = new Label();
Label* labelWaiting = new Label();
SDL_Color errorColor = {204, 0, 0, 0xFF}; //rojo

SDL_Renderer* gRenderer = NULL;
vector <Label*> vectorInputs;

bool MundoSBS::conectServer(ClientSocket* client, char *ip, int port) {

    bool success = true;

    if (client->initSocket() == ERROR) {
        //        cout << "Error - socket()" << endl; //loguear
        success = false;
    } else {
        if (client->connect(ip, port) == ERROR) {
            //            printf("error al conectarse \n"); //loguear
            errorLabel->setLabelText("No se pudo establecer la conexion.");

            success = false;
        } else {
            //            printf("Conectado\n");
            errorLabel->setLabelText("");

        }
    }
    return success;
}

bool MundoSBS::loadLabels() {
    //Loading success flag
    bool success = true;

    //Colores para los labels
    SDL_Color textColor = {255, 128, 0, 0xFF}; //negro
    SDL_Color inputColor = {96, 96, 96, 0xFF}; //gris
    char* fontPath = "Fonts/emulogic.ttf";

    labelIP->setLabelStyle(fontPath, 14, textColor);
    labelPuerto->setLabelStyle(fontPath, 14, textColor);
    labelUsuario->setLabelStyle(fontPath, 14, textColor);
    labelWaiting->setLabelStyle(fontPath, 8, textColor);


    labelIP->setLabelText("IP: ");
    labelPuerto->setLabelText("PUERTO: ");
    labelUsuario->setLabelText("USUARIO: ");
    labelWaiting->setLabelText("Bienvenido al juego!!!! Deberas aguardar a que todos los jugadores esten conectados para iniciar");

    labelIP->createLabelTexture(&gRenderer);
    labelPuerto->createLabelTexture(&gRenderer);
    labelUsuario->createLabelTexture(&gRenderer);
    labelWaiting->createLabelTexture(&gRenderer);

    //The current input text.


        inputIP->setLabelText("10.42.0.66");
    //    inputIP->setLabelText("10.42.0.69");
//    inputIP->setLabelText("127.0.0.1");
    inputIP->setLabelStyle(fontPath, 14, inputColor);
    inputIP->createLabelTexture(&gRenderer);

    inputPuerto->setLabelText("8080");
    inputPuerto->setLabelStyle(fontPath, 14, inputColor);
    inputPuerto->createLabelTexture(&gRenderer);

    inputUsuario->setLabelText("Ingrese USUARIO");
    inputUsuario->setLabelStyle(fontPath, 14, inputColor);
    inputUsuario->createLabelTexture(&gRenderer);

    vectorInputs.push_back(inputIP);
    vectorInputs.push_back(inputPuerto);
    vectorInputs.push_back(inputUsuario);

    return success;
}

bool MundoSBS::goodByePlayer() {

    Window* myWindow;
    SDL_Event myEvent;
    bool escapar;
    escapar = false;
    myWindow = new Window("SBS - Good Bye", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN, &gRenderer);
    if (!(myWindow->isInit())) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la ventana de SDL\n");
        //        cout << "fallo el init" << endl;
    } else if (TTF_Init() == -1) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la ventana de SDL. SDL_ttf Error: ");
        myLogFile->writeInLog(2, TTF_GetError());
        myLogFile->writeInLog(2, "\n");
    } else {
        SBSImage* background = new SBSImage();
        //        if (!(background->loadMedia("Img/background5.jpg", &gRenderer))) {        
        if (!(background->loadMedia("Img/defaultBackground.png", &gRenderer))) {
            myLogFile->writeInLog(1, "[1] Error al cargar la imagen de fondo. Se cargara la imagen default [SCREEN_BACKGROUND] \n");
            background->loadMedia(SCREEN_BACKGROUND, &gRenderer);
            //            cout << "fallo subir imagen" << endl;
        }
        Label* byeLabel = new Label();
        SDL_Color byeColor = {255, 128, 0, 0xFF}; //naranja
        byeLabel->setLabelText("  Lo sentimos! Se desconecto el servidor.  Vuelva a ingresar mas tarde.");
        SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(gRenderer);
        SDL_RenderCopy(gRenderer, background->getTexture(), NULL, NULL);
        byeLabel->printLabel("Fonts/emulogic.ttf", 11, byeColor, &gRenderer, 0, 300);
        SDL_RenderPresent(gRenderer);
        while (!escapar) {
            if (SDL_PollEvent(&myEvent)) {
                if ((myEvent.type == SDL_QUIT) || (myEvent.key.keysym.sym == SDLK_ESCAPE)) {
                    escapar = true;
                    this->endMain = true;
                }
            }
        }
        delete background;
        delete myWindow;
        SDL_DestroyRenderer(gRenderer);
        gRenderer = NULL;
        IMG_Quit();
        SDL_Quit();
    }
}

bool MundoSBS::initButton(ClientSocket * client) {
    bool quit = false;
    bool pressed = false;
    Window* gWindow;

    SDL_Event event;

    //    char* ip;

    gWindow = new Window("SBS - Cliente", 500, 500, SDL_WINDOW_SHOWN, &gRenderer);
    if (!(gWindow->isInit())) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la ventana de SDL.\n");
    } else if (TTF_Init() == -1) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la fuente de SDL.n");
    } else {
        SBSImage* background = new SBSImage();
        Button* startButton = new Button();
        if (!(background->loadMedia("Img/fondoLogIn.png", &gRenderer))) {
            myLogFile->writeInLog(1, "[1] Error al cargar la imagen de fondo.\n");
            background->loadMedia(SCREEN_BACKGROUND, &gRenderer);
            //            cout << "fallo subir imagen" << endl;
        } else {
            if (!startButton->loadSprite(SCREEN_WIDTH, SCREEN_HEIGHT, &gRenderer)) {
                myLogFile->writeInLog(1, "[1] Error al cargar la imagen del boton. \n");
                //                printf("Failed to load media!\n");
            } else {
                if (!loadLabels()) {
                    myLogFile->writeInLog(1, "[1] Error al cargar labels. \n");
                } else {

                    vector <string> inputText = {"", "", ""};
                    //string myText = "";
                    int posInput = 0;
                    //Enable text input
                    SDL_StartTextInput();

                    while (!quit) {
                        //The rerender text flag
                        bool renderText = false;
                        if (SDL_PollEvent(&event)) {
                            if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
                                quit = true;
                                pressed = false;
                            } else {
                                //Special key input
                                if (event.type == SDL_KEYDOWN) {
                                    //Handle TAB
                                    if (event.key.keysym.sym == SDLK_TAB) {
                                        if (posInput == 2) {
                                            posInput = 0;
                                        } else {
                                            posInput = posInput + 1;
                                        }
                                    }
                                    //Handle backspace
                                    if (event.key.keysym.sym == SDLK_BACKSPACE && (inputText.at(posInput).length() > 0)) {
                                        //lop off character

                                        inputText.at(posInput).pop_back();
                                        renderText = true;
                                    }//Handle copy
                                    else if (event.key.keysym.sym == SDLK_c && SDL_GetModState() & KMOD_CTRL) {
                                        SDL_SetClipboardText(inputText.at(posInput).c_str());
                                    }//Handle paste
                                    else if (event.key.keysym.sym == SDLK_v && SDL_GetModState() & KMOD_CTRL) {
                                        inputText[posInput] = SDL_GetClipboardText();
                                        renderText = true;
                                    }
                                }//Special text input event
                                else if (event.type == SDL_TEXTINPUT) {
                                    //Not copy or pasting
                                    if (!((event.text.text[ 0 ] == 'c' || event.text.text[ 0 ] == 'C') && (event.text.text[ 0 ] == 'v' || event.text.text[ 0 ] == 'V') && SDL_GetModState() & KMOD_CTRL)) {
                                        //Append character
                                        inputText[posInput] += event.text.text;
                                        renderText = true;
                                    }
                                }
                            }
                        }
                        if (renderText) {
                            vectorInputs.at(posInput)->setLabelText(inputText.at(posInput));
                            vectorInputs.at(posInput)->createLabelTexture(&gRenderer);
                        }
                        if (startButton->handleEvent(&event)) {

                            // Se inicia la conexion al server con el ip y puerto dado
                            //#NOTA: IP Y PUERTO HARDCODE.
                            char* ip = (char*) vectorInputs.at(0)->getLabelText().c_str();
                            int port = stoi(vectorInputs.at(1)->getLabelText());
                            //                            char ip[] = "10.42.0.69";
                            //                            int port = 8080;
                            //                            char ip[] = "127.0.0.1";
                            char myName [8];
//                            cout << ip << " " << port << endl;
                            strcpy(myName, vectorInputs.at(2)->getLabelText().c_str());

                            if (this->initWindowGame(client, ip, port, myName) != ERROR) {
                                pressed = true;
                                quit = true;
                            }
                        }
                        SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
                        SDL_RenderClear(gRenderer);
                        SDL_RenderCopy(gRenderer, background->getTexture(), NULL, NULL);
                        startButton->render(&gRenderer);

                        //Render text textures
                        labelIP->renderLabel(&gRenderer, 0, 0);
                        labelPuerto->renderLabel(&gRenderer, 0, 50);
                        labelUsuario->renderLabel(&gRenderer, 0, 100);
                        // meter en un for
                        if (vectorInputs.at(0)->getLabelText().length() != 0) {
                            vectorInputs.at(0)->renderLabel(&gRenderer, labelIP->getWidht() + 75, 0);
                        }

                        if (vectorInputs.at(1)->getLabelText().length() != 0) {
                            vectorInputs.at(1)->renderLabel(&gRenderer, labelIP->getWidht() + 75, 50);
                        }

                        if (vectorInputs.at(2)->getLabelText().length() != 0) {
                            vectorInputs.at(2)->renderLabel(&gRenderer, labelIP->getWidht() + 75, 100);
                        }
                        //fin de codigo a meter en un for

                        errorLabel->printLabel("Fonts/emulogic.ttf", 14, errorColor, &gRenderer, 0, 300);

                        //Update screen
                        SDL_RenderPresent(gRenderer);
                    }
                }
                //Disable text input
                SDL_StopTextInput();
            }
        }
        delete background;
        delete startButton;
    }
    delete gWindow;
    SDL_DestroyRenderer(gRenderer);
    gRenderer = NULL;
    IMG_Quit();
    SDL_Quit();
    return pressed;
}

bool MundoSBS::levelFinished(ClientSocket * client) {

    //    bool quit = false;
    //    Window* myWindow;
    //    SDL_Event event;
    //    struct NewPlayer myP;
    //    string nameWindow = "SBS - ";
    //    nameWindow += myP.nombre;
    //    myWindow = new Window(nameWindow, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN, &gRenderer);
    //    this->gWindow = myWindow;
    //    SBSImage* backWaiting = new SBSImage();
    //    SBSImage* logBox = new SBSImage();
    //    SDL_Rect Player_rect; //create a rect
    //
    //    if (!(gWindow->isInit())) {
    //        myLogFile->writeInLog(2, "[2] Fallo al inicializar la ventana de SDL.\n");
    //    } else if (TTF_Init() == -1) {
    //        myLogFile->writeInLog(2, "[2] Fallo al inicializar la fuente de SDL.n");
    //    } else {
    //
    //        if (!(backWaiting->loadMedia("Img/black.png", &gRenderer))) {
    //            myLogFile->writeInLog(1, "[1] Error al cargar la imagen de fondo.\n");
    //            backWaiting->loadMedia(SCREEN_BACKGROUND, &gRenderer);
    //        }
    //        if (!loadLabels()) {
    //            myLogFile->writeInLog(1, "[1] Error al cargar labels. \n");
    //        }
    //        string pathBox;
    //        pathBox="Img/";
    //        pathBox.append(myP.characterId);
    //        pathBox.append("/box");
    //        pathBox.append(myP.characterId);
    //        pathBox.append(".png");
    //        logBox->loadMedia(pathBox, &gRenderer);
    //        Player_rect.x = 150; //controls the rect's x coordinate
    //        Player_rect.y = 200; // controls the rect's y coordinte
    //        Player_rect.w = logBox->getWidth(); // controls the width of the rect
    //        Player_rect.h = logBox->getHeight(); // controls the height of the rect
    //
    //        if (!quit) {
    //            if (SDL_PollEvent(&event)) {
    //                if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
    //                    quit = true;
    //                }
    //            }
    //            SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
    //            SDL_RenderClear(gRenderer);
    //            SDL_RenderCopy(gRenderer, backWaiting->getTexture(), NULL, NULL);
    //            SDL_RenderCopy(gRenderer, logBox->getTexture(), NULL, &Player_rect);
    //            labelWaiting->renderLabel(&gRenderer, 10, 570);
    //            //Update screen
    //            SDL_RenderPresent(gRenderer);
    //            this->recvNextPlayer(client);
    //        }
    //    }
    //    //Disable text input
    //    SDL_StopTextInput();
    //    delete backWaiting;
    //    delete myWindow;
    //    SDL_DestroyRenderer(gRenderer);
    //    gRenderer = NULL;
    //    IMG_Quit();
    //    SDL_Quit();
    //    return quit;

}

//Recibe datos desde el servidor para iniciar la ventana del juego.

int MundoSBS::initWindowGame(ClientSocket* client, char* ip, int port, char name [8]) {
    //    cout << "Entra a initWindowGame" << endl;
    if (this->conectServer(client, ip, port)) {
        /**********************************************************************
         *  DATOS DESDE EL SERVIDOR PARA INICIAR EL JUEGO.
         **********************************************************************/
        //NOMBRE DEL PLAYER
        struct Jugador myPlayer;
        strcpy(myPlayer.nombre, name);
        int lenPlayer = sizeof (myPlayer);
        client->sendAll(&myPlayer, lenPlayer);
        //        cout << "NAME: " << name << endl;
        //VENTANA
        struct Pantalla window;
        int len = sizeof (window);
        this->recv(client, &window, len); //recv con temiOut.

        if (window.type == ID_WINDOW) {

            int cant = window.elements; // cantidad de elementos que voy a recibir        
            //OBJETOS DEL MAPA.
            int lenObject = sizeof (struct ObjectInit);
            for (int i = 0; i < cant; i++) { // dado que recibi el 1ro, hago (total-1)
                struct ObjectInit object;
                this->recv(client, &object, lenObject);
                this->worldObjects.push_back(object);
            }
            this->window = window;

            //            cout << "maxxxxxxxxxxxxxxxxxxxxxx    " << this->window.maxPlayers << endl;
        } else {
            // debo esperar a que haya capacidad en el juego

            bool ok = this->waitForStart(client);

            if (ok) {
                // me guardó la info de pantalla valida 
                int cant = this->window.elements; // cantidad de elementos que voy a recibir        
                //OBJETOS DEL MAPA.
                int lenObject = sizeof (struct ObjectInit);
                for (int i = 0; i < cant; i++) { // dado que recibi el 1ro, hago (total-1)
                    struct ObjectInit object;
                    this->recv(client, &object, lenObject);
                    this->worldObjects.push_back(object);
                }

            } else {
                // si apretó ESC o QUIT
                return -1;
                //            myLogFile->writeInLog(1, "[1] No hay mas capacidad en el juego.. Es muy popular.\n");
            }
        }

        // recibo mis compañeros que ya se habian conectado
        struct NewPlayer iniPlayer;
        bool isGarbage = true;
        while (isGarbage) {
            struct NewPlayer auxPlayer;
            len = sizeof (auxPlayer);
            this->recv(client, &auxPlayer, len);
            if ((auxPlayer.characterId < 5) && (auxPlayer.characterId >= 0)) {
                iniPlayer = auxPlayer;
                isGarbage = false;
            }
        }

        if (iniPlayer.connected > 0) {

            this->allPlayers.push_back(iniPlayer);
            int last = iniPlayer.connected - 1; // descuento el que acaba de llegar

            //            cout << "LASTTTT " << last << endl;
            if (last > 0) {
                for (int j = 0; j < last; j++) {
                    struct NewPlayer newPlayer;
                    this->recv(client, &newPlayer, len);
                    //                    cout << "recv player (initWindowGame): " << newPlayer.characterId << " " << newPlayer.nombre << endl;

                    this->allPlayers.push_back(newPlayer);
                }
            }
        }

    } else {
        myLogFile->writeInLog(2, "[2] Ha ocurrido un error al intentar conectarse al servidor\n");
        return -1;
    }

    // me agrego a la lista
    struct NewPlayer myData;
    myData.characterId = window.characterId;

//    cout << "Soy Jugador " << window.characterId << endl;
    strcpy(myData.nombre, name);
    myData.lifes = INITIAL_LIFES;
    myData.score = INITIAL_SCORE;
    this->allPlayers.push_back(myData);

    //    cout << "size playerssssssssssssssssssssss " << this->allPlayers.size() << endl;

    myLogFile->writeInLog(0, "[0] Se ha contectado al servidor con ip: ");
    myLogFile->writeInLog(0, ip);
    myLogFile->writeInLog(0, " y puerto: ");
    myLogFile->writeInLog(0, to_string(port));
    myLogFile->writeInLog(0, "\n");

    return 0;
}

int MundoSBS::receiveLevelTwo(ClientSocket* client) {
    //    cout << "entro al receive level two " << endl;

    /**********************************************************************
     *  DATOS DESDE EL SERVIDOR PARA INICIAR EL JUEGO.
     **********************************************************************/
    int lenObject = sizeof (struct ObjectInit);
    struct ObjectInit object2;
    this->recv(client, &object2, lenObject);
    int cant = object2.cantElementosEnviados; // cantidad de elementos que voy a recibir
    //    cout << "elementos a recibir: " << cant << endl;

    //limpia vector de worldObjects para volver a cargarlo
    int tamObj2 = this->worldObjects2.size();
    for (int i = 0; i < tamObj2; i++) {
        this->worldObjects2.pop_back();
    }

    this->worldObjects2.push_back(object2);
    //OBJETOS DEL MAPA.
    for (int i = 0; i < (cant - 1); i++) { // dado que recibi el 1ro, hago (total-1)        
        struct ObjectInit object;
        this->recv(client, &object, lenObject);
        this->worldObjects2.push_back(object);
    }

    return 0;

}

bool MundoSBS::waitForStart(ClientSocket* client) {

    bool quit = false;
    bool stillWaiting = true;
    Window* myWindow;
    SDL_Event event;

    myWindow = new Window("SBS - Cliente", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN, &gRenderer);
    this->gWindow = myWindow;
    SBSImage* backWaiting = new SBSImage();

    if (!(gWindow->isInit())) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la ventana de SDL.\n");
    } else if (TTF_Init() == -1) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la fuente de SDL.n");
    } else {

        if (!(backWaiting->loadMedia("Img/waitForStart.png", &gRenderer))) {
            myLogFile->writeInLog(1, "[1] Error al cargar la imagen de fondo.\n");
            backWaiting->loadMedia(SCREEN_BACKGROUND, &gRenderer);
        }
        if (!loadLabels()) {
            myLogFile->writeInLog(1, "[1] Error al cargar labels. \n");
        }

        while (stillWaiting) {
            usleep(50000);

            if (!quit) {
                if (SDL_PollEvent(&event)) {
                    if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
                        quit = false;
                        break;
                    }
                }
                SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
                SDL_RenderClear(gRenderer);
                SDL_RenderCopy(gRenderer, backWaiting->getTexture(), NULL, NULL);
                //Update screen
                SDL_RenderPresent(gRenderer);
            }

            //VENTANA
            struct Pantalla window;
            int len = sizeof (window);
            this->recv(client, &window, len); //recv con temiOut.

            if (window.type == ID_WINDOW) {

                stillWaiting = false;
                quit = true;
                this->window = window;
            }

        }

        //Disable text input
        SDL_StopTextInput();
        delete backWaiting;
        delete myWindow;
        SDL_DestroyRenderer(gRenderer);
        gRenderer = NULL;
        IMG_Quit();
        SDL_Quit();
        this->waitingForReload = false;
        return quit;
    }
}

bool MundoSBS::waitingPlayersToReload() {

    bool quit = false;
    bool stillWaiting = true;
    Window* myWindow;
    SDL_Event event;

    myWindow = new Window("SBS - Cliente", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN, &gRenderer);
    this->gWindow = myWindow;
    SBSImage* backWaiting = new SBSImage();

    if (!(gWindow->isInit())) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la ventana de SDL.\n");
    } else if (TTF_Init() == -1) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la fuente de SDL.n");
    } else {

        if (!(backWaiting->loadMedia("Img/waitingPlayers.png", &gRenderer))) {
            myLogFile->writeInLog(1, "[1] Error al cargar la imagen de fondo.\n");
            backWaiting->loadMedia(SCREEN_BACKGROUND, &gRenderer);
        }
        if (!loadLabels()) {
            myLogFile->writeInLog(1, "[1] Error al cargar labels. \n");
        }

        struct Event eventPulse;
        eventPulse.pressed = '@';

        while (stillWaiting) {
            usleep(50000);
            this->player->pushEvent(eventPulse); //envio los datos 


            if (!quit) {
                if (SDL_PollEvent(&event)) {
                    if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
                        quit = true;

                        //                        TODO:: corregir salir bien
                    }
                }
                SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
                SDL_RenderClear(gRenderer);
                SDL_RenderCopy(gRenderer, backWaiting->getTexture(), NULL, NULL);
                labelWaiting->renderLabel(&gRenderer, 10, 570);
                //Update screen
                SDL_RenderPresent(gRenderer);
            }
            struct ObjectInit obj;
            bool finished = this->player->tryPop(obj);

            if (finished) {
                if (obj.level == -1)
                    stillWaiting = false;
            }

        }


        //Disable text input
        SDL_StopTextInput();
        delete backWaiting;
        delete myWindow;
        SDL_DestroyRenderer(gRenderer);
        gRenderer = NULL;
        IMG_Quit();
        SDL_Quit();
        this->waitingForReload = false;
        return quit;
    }
}

bool MundoSBS::waitingPlayers(ClientSocket * client) {

    bool quit = false;
    Window* myWindow;
    SDL_Event event;

    myWindow = new Window("SBS - Cliente", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN, &gRenderer);
    this->gWindow = myWindow;
    SBSImage* backWaiting = new SBSImage();
    SBSImage* logBox = new SBSImage();
    SBSImage* logBox2 = new SBSImage();
    SBSImage* logBox3 = new SBSImage();
    SBSImage* logBox4 = new SBSImage();
    SDL_Rect Player_rect, Player_rect2, Player_rect3, Player_rect4; //create a rect

    if (!(gWindow->isInit())) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la ventana de SDL.\n");
    } else if (TTF_Init() == -1) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la fuente de SDL.n");
    } else {

        if (!(backWaiting->loadMedia("Img/waitingBackground.png", &gRenderer))) {
            myLogFile->writeInLog(1, "[1] Error al cargar la imagen de fondo.\n");
            backWaiting->loadMedia(SCREEN_BACKGROUND, &gRenderer);
        }
        if (!loadLabels()) {
            myLogFile->writeInLog(1, "[1] Error al cargar labels. \n");
        }
        if (this->allPlayers.empty()) {
            //            cout << "esta empty" << endl;
            logBox->loadMedia("Img/box.png", &gRenderer);
            Player_rect.x = 450; //controls the rect's x coordinate
            Player_rect.y = 50; // controls the rect's y coordinte
            Player_rect.w = logBox->getWidth(); // controls the width of the rect
            Player_rect.h = logBox->getHeight(); // controls the height of the rect

            logBox2->loadMedia("Img/box.png", &gRenderer);
            Player_rect2.x = logBox->getWidth() + 500; //controls the rect's x coordinate
            Player_rect2.y = 50; // controls the rect's y coordinte
            Player_rect2.w = logBox2->getWidth(); // controls the width of the rect
            Player_rect2.h = logBox2->getHeight(); // controls the height of the rect

            logBox3->loadMedia("Img/box.png", &gRenderer);
            Player_rect3.x = 450; //controls the rect's x coordinate
            Player_rect3.y = logBox->getHeight() + 100; // controls the rect's y coordinte
            Player_rect3.w = logBox3->getWidth(); // controls the width of the rect
            Player_rect3.h = logBox3->getHeight(); // controls the height of the rect

            logBox4->loadMedia("Img/box.png", &gRenderer);
            Player_rect4.x = logBox3->getWidth() + 500; //controls the rect's x coordinate
            Player_rect4.y = logBox2->getHeight() + 100; // controls the rect's y coordinte
            Player_rect4.w = logBox4->getWidth(); // controls the width of the rect
            Player_rect4.h = logBox4->getHeight(); // controls the height of the rect
        } else {
            while (!this->startGame(client)) {

                switch (this->allPlayers.size()) {
                    case 1:
                        logBox->loadMedia("Img/1/box1.png", &gRenderer);
                        Player_rect.x = 450; //controls the rect's x coordinate
                        Player_rect.y = 50; // controls the rect's y coordinte
                        Player_rect.w = logBox->getWidth(); // controls the width of the rect
                        Player_rect.h = logBox->getHeight(); // controls the height of the rect

                        logBox2->loadMedia("Img/box.png", &gRenderer);
                        Player_rect2.x = logBox->getWidth() + 500; //controls the rect's x coordinate
                        Player_rect2.y = 50; // controls the rect's y coordinte
                        Player_rect2.w = logBox2->getWidth(); // controls the width of the rect
                        Player_rect2.h = logBox2->getHeight(); // controls the height of the rect

                        logBox3->loadMedia("Img/box.png", &gRenderer);
                        Player_rect3.x = 450; //controls the rect's x coordinate
                        Player_rect3.y = logBox->getHeight() + 100; // controls the rect's y coordinte
                        Player_rect3.w = logBox3->getWidth(); // controls the width of the rect
                        Player_rect3.h = logBox3->getHeight(); // controls the height of the rect

                        logBox4->loadMedia("Img/box.png", &gRenderer);
                        Player_rect4.x = logBox3->getWidth() + 500; //controls the rect's x coordinate
                        Player_rect4.y = logBox2->getHeight() + 100; // controls the rect's y coordinte
                        Player_rect4.w = logBox4->getWidth(); // controls the width of the rect
                        Player_rect4.h = logBox4->getHeight(); // controls the height of the rect                                                          
                        break;
                    case 2:
                        logBox->loadMedia("Img/1/box1.png", &gRenderer);
                        Player_rect.x = 450; //controls the rect's x coordinate
                        Player_rect.y = 50; // controls the rect's y coordinte
                        Player_rect.w = logBox->getWidth(); // controls the width of the rect
                        Player_rect.h = logBox->getHeight(); // controls the height of the rect

                        logBox2->loadMedia("Img/2/box2.png", &gRenderer);
                        Player_rect2.x = logBox->getWidth() + 500; //controls the rect's x coordinate
                        Player_rect2.y = 50; // controls the rect's y coordinte
                        Player_rect2.w = logBox2->getWidth(); // controls the width of the rect
                        Player_rect2.h = logBox2->getHeight(); // controls the height of the rect

                        logBox3->loadMedia("Img/box.png", &gRenderer);
                        Player_rect3.x = 450; //controls the rect's x coordinate
                        Player_rect3.y = logBox->getHeight() + 100; // controls the rect's y coordinte
                        Player_rect3.w = logBox3->getWidth(); // controls the width of the rect
                        Player_rect3.h = logBox3->getHeight(); // controls the height of the rect

                        logBox4->loadMedia("Img/box.png", &gRenderer);
                        Player_rect4.x = logBox3->getWidth() + 500; //controls the rect's x coordinate
                        Player_rect4.y = logBox2->getHeight() + 100; // controls the rect's y coordinte
                        Player_rect4.w = logBox4->getWidth(); // controls the width of the rect
                        Player_rect4.h = logBox4->getHeight(); // controls the height of the rect 
                        break;
                    case 3:
                        logBox->loadMedia("Img/1/box1.png", &gRenderer);
                        Player_rect.x = 450; //controls the rect's x coordinate
                        Player_rect.y = 50; // controls the rect's y coordinte
                        Player_rect.w = logBox->getWidth(); // controls the width of the rect
                        Player_rect.h = logBox->getHeight(); // controls the height of the rect

                        logBox2->loadMedia("Img/2/box2.png", &gRenderer);
                        Player_rect2.x = logBox->getWidth() + 500; //controls the rect's x coordinate
                        Player_rect2.y = 50; // controls the rect's y coordinte
                        Player_rect2.w = logBox2->getWidth(); // controls the width of the rect
                        Player_rect2.h = logBox2->getHeight(); // controls the height of the rect

                        logBox3->loadMedia("Img/3/box3.png", &gRenderer);
                        Player_rect3.x = 450; //controls the rect's x coordinate
                        Player_rect3.y = logBox->getHeight() + 100; // controls the rect's y coordinte
                        Player_rect3.w = logBox3->getWidth(); // controls the width of the rect
                        Player_rect3.h = logBox3->getHeight(); // controls the height of the rect

                        logBox4->loadMedia("Img/box.png", &gRenderer);
                        Player_rect4.x = logBox3->getWidth() + 500; //controls the rect's x coordinate
                        Player_rect4.y = logBox2->getHeight() + 100; // controls the rect's y coordinte
                        Player_rect4.w = logBox4->getWidth(); // controls the width of the rect
                        Player_rect4.h = logBox4->getHeight(); // controls the height of the rect                                                          
                        break;
                    case 4:
                        logBox->loadMedia("Img/1/box1.png", &gRenderer);
                        Player_rect.x = 450; //controls the rect's x coordinate
                        Player_rect.y = 50; // controls the rect's y coordinte
                        Player_rect.w = logBox->getWidth(); // controls the width of the rect
                        Player_rect.h = logBox->getHeight(); // controls the height of the rect

                        logBox2->loadMedia("Img/2/box2.png", &gRenderer);
                        Player_rect2.x = logBox->getWidth() + 500; //controls the rect's x coordinate
                        Player_rect2.y = 50; // controls the rect's y coordinte
                        Player_rect2.w = logBox2->getWidth(); // controls the width of the rect
                        Player_rect2.h = logBox2->getHeight(); // controls the height of the rect

                        logBox3->loadMedia("Img/3/box3.png", &gRenderer);
                        Player_rect3.x = 450; //controls the rect's x coordinate
                        Player_rect3.y = logBox->getHeight() + 100; // controls the rect's y coordinte
                        Player_rect3.w = logBox3->getWidth(); // controls the width of the rect
                        Player_rect3.h = logBox3->getHeight(); // controls the height of the rect

                        logBox4->loadMedia("Img/4/box4.png", &gRenderer);
                        Player_rect4.x = logBox3->getWidth() + 500; //controls the rect's x coordinate
                        Player_rect4.y = logBox2->getHeight() + 100; // controls the rect's y coordinte
                        Player_rect4.w = logBox4->getWidth(); // controls the width of the rect
                        Player_rect4.h = logBox4->getHeight(); // controls the height of the rect 
                        break;
                }


                if (!quit) {
                    if (SDL_PollEvent(&event)) {
                        if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
                            quit = true;
                        }
                    }
                    SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
                    SDL_RenderClear(gRenderer);
                    SDL_RenderCopy(gRenderer, backWaiting->getTexture(), NULL, NULL);
                    SDL_RenderCopy(gRenderer, logBox->getTexture(), NULL, &Player_rect);
                    SDL_RenderCopy(gRenderer, logBox2->getTexture(), NULL, &Player_rect2);
                    SDL_RenderCopy(gRenderer, logBox3->getTexture(), NULL, &Player_rect3);
                    SDL_RenderCopy(gRenderer, logBox4->getTexture(), NULL, &Player_rect4);
                    labelWaiting->renderLabel(&gRenderer, 10, 570);
                    //Update screen
                    SDL_RenderPresent(gRenderer);
                    this->recvNextPlayer(client);
                }
            }
            //Disable text input
            SDL_StopTextInput();
            delete backWaiting;
            delete myWindow;
            SDL_DestroyRenderer(gRenderer);
            gRenderer = NULL;
            IMG_Quit();
            SDL_Quit();
            return quit;
        }
    }
}

void MundoSBS::checkQuitOrZoom(SDL_Event* event, bool* quit, bool* zoomIn, bool* zoomOut) {
    if ((event->type == SDL_QUIT) || (event->key.keysym.sym == SDLK_ESCAPE)) {
        *quit = true;
        this->endMain = true;
        this->salioManualmente = true;
    }
    if ((event->key.state == SDL_PRESSED) && (event->key.keysym.sym == SDLK_PLUS || event->key.keysym.sym == SDLK_KP_PLUS)) {
        *zoomIn = true;
    }
    if ((event->key.state == SDL_PRESSED) && (event->key.keysym.sym == SDLK_MINUS || event->key.keysym.sym == SDLK_KP_MINUS)) {
        *zoomOut = true;
    }
    if ((event->key.state == SDL_RELEASED) && (event->key.keysym.sym == SDLK_PLUS || event->key.keysym.sym == SDLK_KP_PLUS)) {
        *zoomIn = false;
    }
    if ((event->key.state == SDL_RELEASED) && (event->key.keysym.sym == SDLK_MINUS || event->key.keysym.sym == SDLK_KP_MINUS)) {
        *zoomOut = false;
    }

}

void MundoSBS::createFigures(SDL_Renderer * renderer) {
    struct ObjectInit data;

    for (int k = 0; k < this->worldObjects.size(); k++) {
        data = this->worldObjects.at(k);
        if ((!((data.objectId == 0) && (data.idCharacter == 0))) && (data.idCharacter != -1)) {
            if (data.estatico) {
                Object* object = new Object(data, renderer, data.objectId, data.imageId);
                this->staticObjects.push_back(object);
            } else {
                //            cout << "ubicacionnnnn" << data.ubicDyn << endl;
                if (data.idCharacter == VACIO) { // no es character
                    Object* object = new Object(data, renderer, data.objectId, data.imageId);
                    this->dynamicObjects.push_back(object);
                } else {
                    //                cout << "soy character: " << this->window.characterId <<" agrego personaje: " << data.idCharacter<<" x " <<data.x <<" y "<<data.y << endl;
                    //                Character* character = new Character(data.x, data.y, &renderer, data.idCharacter);
                    //                this->dynamicObjects.push_back(character);
                    //            }
                    if (data.idCharacter < 10) {
                        Character* character = new Character(data.x, data.y, &renderer, data.idCharacter);
                        this->dynamicObjects.push_back(character);
                    } else {
                        if (data.idCharacter < 20) {
                            Enemy* enemy = new Enemy(data.x, data.y, &renderer, data.idCharacter);
                            this->dynamicObjects.push_back(enemy);
                        } else {
                            Boss* boss = new Boss(data.x, data.y, &renderer);
                            this->dynamicObjects.push_back(boss);
                        }
                    }
                }
            }
        }
    }
}

void MundoSBS::createFigures2(SDL_Renderer * renderer) {
    struct ObjectInit data;
    for (int k = 0; k < this->worldObjects2.size(); k++) {
        data = this->worldObjects2.at(k);
        if ((!((data.objectId == 0) && (data.idCharacter == 0))) && (data.idCharacter != -1)) {
            if (data.idCharacter < 30) {
                if (data.estatico) {
                    Object* object = new Object(data, renderer, data.objectId, data.imageId);
                    this->staticObjects2.push_back(object);
                } else {
                    //            cout << "ubicacionnnnn" << data.ubicDyn << endl;
                    if (data.idCharacter == VACIO) { // no es character
                        Object* object = new Object(data, renderer, data.objectId, data.imageId);
                        this->dynamicObjects2.push_back(object);
                    } else {
                        //                cout << "soy character: " << this->window.characterId <<" agrego personaje: " << data.idCharacter<<" x " <<data.x <<" y "<<data.y << endl;
                        //                Character* character = new Character(data.x, data.y, &renderer, data.idCharacter);
                        //                this->dynamicObjects.push_back(character);
                        //            }
                        if (data.idCharacter < 10) {
                            Character* character = new Character(data.x, data.y, &renderer, data.idCharacter);
                            this->dynamicObjects2.push_back(character);
                        } else {
                            if (data.idCharacter < 20) {
                                Enemy* enemy = new Enemy(data.x, data.y, &renderer, data.idCharacter);
                                this->dynamicObjects2.push_back(enemy);
                            } else {
                                Boss* boss = new Boss(data.x, data.y, &renderer);
                                this->dynamicObjects2.push_back(boss);
                            }
                        }
                    }
                }
            }
            //        cout << "k " << k << endl;
        }
    }
}

bool MundoSBS::initLevel(ClientSocket * client) {

    if (this->reloadLevelOne) {
//        cout << "INICIO NIVEL 1" << endl;
        //#NOTA: Lipio el buffer de datos del cliente.

        struct ObjectInit garbage;
        bool fin = false;
        while (!fin) {
            if (!player->tryPop(garbage)) {
                //no tengo elemento del nivel 1.            
                fin = true;
            }
        }
    }

    // print the number of sample chunk decoders available
    //    printf("There are %d sample chunk deocoders BEFORE available\n", Mix_GetNumChunkDecoders());

    //Stop the music
    Mix_HaltMusic();

    // print the number of sample chunk decoders available
    //    printf("There are %d sample chunk deocoders AFTER available\n", Mix_GetNumChunkDecoders());
    //  halt playback on all channels
    //Mix_HaltChannel(-1);

    bool quit = false;
    bool zoomIn = false;
    bool zoomOut = false;
    struct NewPlayer myP;
    //The music that will be played
    Mix_Music *gMusic = NULL;
    //Musicalizacion de los eventos
    //The sound effects that will be used
    Mix_Chunk *gHigh = NULL; // saltar
    Mix_Chunk *gLife = NULL; //bonus de vida o rayo
    Mix_Chunk *gDie = NULL; // perder una vida

    //Para escribir Score y Lifes
    SDL_Texture* Message;
    SDL_Texture* Message2;
    SDL_Rect Message_rect; //create a rect
    SDL_Rect Message2_rect; //create a rect

    SDL_Texture* gameOverText;
    SDL_Rect gameOverRect;

    SDL_Renderer* gRenderer = NULL;
    SDL_Event event;
    string nameWindow = "SBS - ";
    nameWindow += vectorInputs.at(2)->getLabelText();


    gWindow = new Window(nameWindow, this->window.pxWidth, this->window.pxHeight, SDL_WINDOW_SHOWN, &gRenderer);
    if (!(gWindow->isInit())) {
        //        cout << "fallo el init" << endl;
        myLogFile->writeInLog(2, "[2] Error al cargar ventana de juego\n");
    } else {

        SBSImage* background = new SBSImage();

        if (TTF_Init()) {
            myLogFile->writeInLog(2, "[2] Ha ocurrido un error al cargar la imagen: ");
            myLogFile->writeInLog(2, TTF_GetError());
            myLogFile->writeInLog(2, "\n");
        }
        TTF_Font* Sans;
        Sans = TTF_OpenFont("Fonts/emulogic.ttf", 12); //this opens a font style and sets a size
        if (!Sans) {
            myLogFile->writeInLog(1, "[1] No se encontro la fuente\n");
        }
        if (SDL_Init(SDL_INIT_AUDIO) < 0) {
            printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        }
        if (!(background->loadMedia("Img/F2.png", &gRenderer))) {
            myLogFile->writeInLog(2, "[2] Error al cargar la imagen de fondo. \n");
        } else {

            //Initialize SDL_mixer
            if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) {
                printf("SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError());
            }

            //Load music
            gMusic = Mix_LoadMUS("Music/MarioSong.wav");
            if (gMusic == NULL) {
                printf("Failed to load beat music! SDL_mixer Error: %s\n", Mix_GetError());

            }
            //Load sound effects
            gHigh = Mix_LoadWAV("Music/smb_jump-super.wav");
            if (gHigh == NULL) {
                printf("Failed to load high sound effect! SDL_mixer Error: %s\n", Mix_GetError());

            }
            //            else cout << "Cargo bien el archivo de musiquita de saltar" << endl;

            gLife = Mix_LoadWAV("Music/smb_1-up.wav");
            if (gLife == NULL) {
                printf("Failed to load bonus sound effect! SDL_mixer Error: %s\n", Mix_GetError());

            }
            gDie = Mix_LoadWAV("Music/smb_fireworks.wav");
            if (gDie == NULL) {
                printf("Failed to load die sound effect! SDL_mixer Error: %s\n", Mix_GetError());

            }

            this->createFigures(gRenderer);
            ScreenManager* screenManager = new ScreenManager(window.luWidth, window.luHeight, window.pxWidth, window.pxHeight, this->window.characterId);

            /******************************************************************
             * CHARACTER
             ******************************************************************/
            if (this->reloadLevelOne) {
                Player* player = this->player;
            } else {
                Player* player = new Player(client);
                // segun lo que dice el server setea un waiting o no
                player->setWaitForReloadGame(this->window.reloadLevel);
                this->player = player;
            }
            bool primeraVez = true;
            bool segundaVez = false;

            string sc = "Score: ";
            string lf = "Lifes: ";
            string go = "GAME OVER";

            usleep(50000);
            player->runThreadRecv();

            // si estoy comenzando en un nivel reiniciado
            if (this->window.reloadLevel != 0) {
                // cambio asi no vuelvo a entrar en esta validacion
                this->window.reloadLevel = 0;

                bool end = false;
                while (!end) {
                    struct ObjectInit obj;
                    bool flag = this->player->tryPop(obj);
                    // espero el flag de inicio nivel 1
                    if (flag) {
                        if (obj.level == 1) {
                            end = true;
                            // ya puede arrancar normalmente
                            this->player->setWaitForReloadGame(0);
                        }
                    }
                }
            }

            player->runThreadSend();

            SDL_Texture* mTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, background->getWidth(), background->getHeight());

            SDL_SetRenderDrawBlendMode(gRenderer, SDL_BLENDMODE_BLEND);
            SDL_SetTextureBlendMode(mTexture, SDL_BLENDMODE_BLEND);
            SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xAA, SDL_BLENDMODE_NONE);

            SDL_EventState(SDL_MOUSEMOTION, 0);

            // this is the color in rgb format, maxing out all would give you the color white, and it will be your text's color
            SDL_Color White = {255, 128, 0, 255};
            // as TTF_RenderText_Solid could only be used on SDL_Surface then you have to create the surface first    

            myLogFile->writeInLog(1, "[1] Se creo la pantalla transparente de Score&Life exitosamente. \n");
            Mix_PlayMusic(gMusic, -1);
            Mix_VolumeMusic(MIX_MAX_VOLUME / 2);
            //            printf("volume is now : %d\n", Mix_VolumeMusic(-1));   
            this->isObserver = false;
            while (!quit) {
                if (player->isInit()) {
                    SDL_SetRenderTarget(gRenderer, mTexture);
                    SDL_RenderClear(gRenderer);
                    SDL_RenderCopy(gRenderer, background->getTexture(), NULL, NULL);

                    struct Event e;
                    int sonar = 0;
                    //int sonarF = 0;

                    //                 if (SDL_PollEvent(&event)) {
                    if (event.key.state == SDL_PRESSED) {
                        e.released = NULL;
                        switch (event.key.keysym.sym) {
                            case SDLK_LEFT:
                                e.pressed = 'L';
                                break;
                            case SDLK_RIGHT:
                                e.pressed = 'R';
                                break;
                            case SDLK_UP:
                                e.pressed = 'U';
                                break;
                            case SDLK_DOWN:
                                e.pressed = 'D';
                                break;
                            case SDLK_SPACE:
                                e.pressed = 'B';
                                break;
                            default:
                                e.pressed = '@';
                                break;
                        }
                    } else {
                        if (event.key.state == SDL_RELEASED) {
                            e.pressed = NULL;
                            switch (event.key.keysym.sym) {
                                case SDLK_LEFT:
                                    e.released = 'L';
                                    break;
                                case SDLK_RIGHT:
                                    e.released = 'R';
                                    break;
                                case SDLK_UP:
                                    e.released = 'U';
                                    break;
                                case SDLK_DOWN:
                                    e.released = 'D';
                                    break;
                                default:
                                    e.released = '@';
                                    break;
                            }
                        } else {
                            e.released = NULL;
                            e.pressed = '@';
                        }
                    }
                    if (primeraVez) {
                        e. released = NULL;
                        e. pressed = 'D';

                    }
                    if (segundaVez) {
                        e. pressed = NULL;
                        e. released = 'D';
                        segundaVez = false;
                    }
                    player->pushEvent(e); //envio los datos 
                    bool end = false;
                    //CAMBIOS MAU
                    int cantidadActualizar = 0;
                    int cantidadPack = 50;
                    struct ObjectInit newData;
                    while (!end) {
                        while (cantidadActualizar <= cantidadPack) {//cantidad de paquetes a actualizar. para luego dibujar el ultimo
                            if (player->tryPop(newData)) {

                                /***********************************************
                                 * PASAR AL NIVEL 2
                                 ***********************************************/
                                //                                cout << "newData: " << newData.level << endl;
                                //asd                                

                                if (newData.level == -1) {
//                                    cout << "IR A WAITING" << endl;
                                    this->waitingForReload = true;

                                    end = true;
                                    quit = true;
                                    break;
                                }

                                if (newData.level == 2) {
//                                    cout << "IR A NIVEL 2" << endl;
                                    end = true;
                                    quit = true;
                                    break;
                                }
                                if (newData.level == 3) {
//                                    cout << "Todos los players perdieron sus vidas" << endl;
                                    end = true;
                                    quit = true;
                                    this->setGameOver(true);
                                    break;
                                }
                                if (newData.level == 4) {
//                                    cout << "Game over + waiting" << endl;
                                    this->setGameOver(true);

                                    // DEBO ESPERAR AL LEVEL -1
                                    struct Event eventPulse;
                                    eventPulse.pressed = '@';

                                    bool stillWaiting = true;
                                    while (stillWaiting) {
                                        usleep(50000);
                                        player->pushEvent(eventPulse);

                                        struct ObjectInit obj;
                                        bool finished = this->player->tryPop(obj);

                                        if (finished) {
                                            if (obj.level == -1)
                                                stillWaiting = false;
                                        }

                                    }

                                    end = true;
                                    quit = true;
                                    this->waitingForReload = true;

                                    break;
                                }

                                if (newData.idCharacter != ID_END_SEND) {
                                    this->updateDynamicObjects(&newData, gRenderer);
                                    for (int j = 0; j < this->dynamicObjects.size(); j++) {
                                        this->dynamicObjects.at(j)->actualize();
                                        if (this->dynamicObjects.at(j)->getCharacterId() == screenManager->getCharacterId()) {
                                            if (primeraVez) {
                                                screenManager->setPosCamera(this->dynamicObjects.at(j)->getPosX(), this->dynamicObjects.at(j)->getPosY());
                                                screenManager->actualizeSettings();
                                                primeraVez = false;
                                                segundaVez = true;
                                            }
                                            screenManager->setCharacterPos(this->dynamicObjects.at(j)->getPosX(), this->dynamicObjects.at(j)->getPosY());
                                            screenManager->actualizeSettings();
                                            //Score y Lifes
                                            struct ObjectInit myObj;
                                            sc = "Score: ";
                                            myObj = this->dynamicObjects.at(j)->getData();
                                            sc.append(to_string(myObj.score));
                                            lf = "Lifes: ";
                                            lf.append(to_string(myObj.lifes));
                                            if (myObj.stateCharacter == 12) {
                                                screenManager->setObserver();
                                                this->isObserver = true;
                                            }
                                        }
                                    }
                                    list<Drawable*> bulletList;
                                    for (int i = 0; i< this->bulletList.size(); i++) {
                                        Drawable* bullet = this->bulletList.at(i);
                                        if (bullet->getData().bulletStat != BULLET_DEAD) {
                                            bullet->actualize();
                                        }
                                    }
                                    cantidadActualizar++;
                                } else { //no se si este else es necesario. Lo dejo por las dudas :P
                                    //                                    end = true;
                                }
                            } else { //cuando size = 0. es necesario hacer un break. Para que el programa siga                                                         
                                break; // salfo de while interno.
                            }
                        }
                        end = true;
                    }

                    //Se actualizan todos los objetos estaticos
                    for (int j = 0; j < this->staticObjects.size(); j++) {
                        this->staticObjects.at(j)->actualize();
                    }


                    //Se dubujan todos los objetos estaticos
                    for (int j = 0; j < this->staticObjects.size(); j++) {
                        this->staticObjects.at(j)->draw();
                    }

                    //Se dibujan todos los objetos dinamicos
                    for (int k = 0; k < this->dynamicObjects.size(); k++) {
                        Drawable* elem = this->dynamicObjects.at(k);
                        if (elem->getCharacterId() == screenManager->getCharacterId()) {
                            //if ((Mix_Playing(1) == 0) && (elem->getData().event.pressed == 'C')) {
                            if (elem->getData().event.pressed == 'C') {
                                Mix_PlayChannel(1, gLife, 0);
                                Mix_VolumeChunk(gLife, MIX_MAX_VOLUME);

                            }
                            if ((elem->getData().stateCharacter == 1) && (sonar == 0)) {
                                if ((Mix_Playing(1) == 0) && (elem->getData().event.pressed == 'U')) {
                                    Mix_PlayChannel(1, gHigh, 0);
                                    Mix_VolumeChunk(gHigh, MIX_MAX_VOLUME);
                                    sonar++;
                                }
                            }
                            if (elem->getData().stateCharacter == 6) {
                                if (Mix_Playing(1) == 0) {
                                    Mix_PlayChannel(1, gDie, 0);
                                    Mix_VolumeChunk(gDie, MIX_MAX_VOLUME);
                                }
                            }
                        }
                        if (elem->getData().imageId != -1) {
                            elem->draw();
                        }
                    }

                    //draw shoot
                    list<Drawable*> bulletList;
                    for (int i = 0; i< this->bulletList.size(); i++) {
                        Drawable* bullet = this->bulletList.at(i);
                        if (bullet->getData().bulletStat != BULLET_DEAD) {
                            bullet->actualize();
                            bullet->draw();
                        }
                    }

                    SDL_Surface* scoreMessage = TTF_RenderText_Solid(Sans, sc.c_str(), White);
                    SDL_Surface* livesMessage = TTF_RenderText_Solid(Sans, lf.c_str(), White);

                    int text_width = scoreMessage->w;
                    int text_height = scoreMessage->h;
                    Message = SDL_CreateTextureFromSurface(gRenderer, scoreMessage); //now you can convert it into a texture

                    int text_widthl = livesMessage->w;
                    int text_heightl = livesMessage->h;
                    Message2 = SDL_CreateTextureFromSurface(gRenderer, livesMessage); //now you can convert it into a texture

                    Message_rect.x = 0; //controls the rect's x coordinate
                    Message_rect.y = 0; // controls the rect's y coordinte
                    Message_rect.w = text_width; // controls the width of the rect
                    Message_rect.h = text_height; // controls the height of the rect

                    Message2_rect.x = 0; //controls the rect's x coordinate
                    Message2_rect.y = text_height + 5; // controls the rect's y coordinte
                    Message2_rect.w = text_widthl; // controls the width of the rect
                    Message2_rect.h = text_heightl; // controls the height of the rect

                    SDL_Surface* GOMessage = TTF_RenderText_Solid(Sans, go.c_str(), White);
                    int text_widthGO = GOMessage->w;
                    int text_heightGO = GOMessage->h;
                    gameOverText = SDL_CreateTextureFromSurface(gRenderer, GOMessage); //now you
                    gameOverRect.x = 200; //controls the rect's x coordinate
                    gameOverRect.y = 200; // controls the rect's y coordinte
                    gameOverRect.w = text_widthGO + 250; // controls the width of the rect
                    gameOverRect.h = text_heightGO + 50; // controls the height of the rect

                    SDL_SetRenderTarget(gRenderer, NULL);
                    screenManager->setZoom(zoomIn, zoomOut);
                    screenManager->actualizeSettings();
                    screenManager->draw(&gRenderer, &mTexture);

                    if (this->isObserver) {
                        SDL_RenderCopy(gRenderer, gameOverText, NULL, &gameOverRect);
                    } else {
                        SDL_RenderCopy(gRenderer, Message, NULL, &Message_rect);
                        SDL_RenderCopy(gRenderer, Message2, NULL, &Message2_rect);
                    }

                    SDL_RenderPresent(gRenderer);

                    SDL_FreeSurface(GOMessage);
                    GOMessage = NULL;
                    SDL_FreeSurface(scoreMessage);
                    scoreMessage = NULL;
                    SDL_FreeSurface(livesMessage);
                    livesMessage = NULL;

                    SDL_DestroyTexture(Message);
                    Message = NULL;
                    SDL_DestroyTexture(Message2);
                    Message2 = NULL;
                    //Fin Score y Lifes

                    if (SDL_PollEvent(&event)) {
                        checkQuitOrZoom(&event, &quit, &zoomIn, & zoomOut);
                    }

                } else {
                    this->goodByePlayer();
                    quit = true;
                }
            }

            //Stop the music
            Mix_HaltMusic();
            delete screenManager;
            SDL_DestroyTexture(mTexture);
            mTexture = NULL;
            delete background;
        }
    }

    //    if (this->getGameOver()) {
    //        bool salir = false;
    //        while (!salir) {
    //            if (SDL_PollEvent(&event)) {
    //                if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
    //                    salir = true;
    //                }
    //                SBSImage* backgroundAntes = new SBSImage();
    //                backgroundAntes->loadMedia("Img/nivel2.png", &gRenderer);
    //                SDL_RenderClear(gRenderer);
    //                SDL_RenderCopy(gRenderer, backgroundAntes->getTexture(), NULL, NULL);
    //                SDL_RenderPresent(gRenderer);
    //            }
    //        }
    //    }

    if (this->getGameOver()) {

        SBSImage* backgroundGO = new SBSImage();
        backgroundGO->loadMedia("Img/gameOver.png", &gRenderer);
        SDL_RenderClear(gRenderer);
        SDL_RenderCopy(gRenderer, backgroundGO->getTexture(), NULL, NULL);
        SDL_RenderPresent(gRenderer);
        if (SDL_PollEvent(&event)) {
            if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
                this->endMain = true;
            }
        }
        usleep(1000000);

        delete backgroundGO;
    }

    delete gWindow;
    SDL_DestroyRenderer(gRenderer);
    gRenderer = NULL;
    IMG_Quit();
    SDL_Quit();
    //Free the sound effects
    Mix_FreeChunk(gHigh);
    gHigh = NULL;
    Mix_FreeChunk(gLife);
    gLife = NULL;
    //Free the music
    Mix_FreeMusic(gMusic);
    gMusic = NULL;
    /***************************************************************************
     *  Elimino/ limpieza de elementos
     ***************************************************************************/

    this->garbageCollector();
//    cout << "Fin Nivel 1" << endl;
    Mix_CloseAudio();
//    cout << "Canales en uso fin nivel 1: " << Mix_AllocateChannels(-1) << endl;


    this->reloadLevelOne = true;


    int tam3 = dynamicObjects.size();
    for (int i = 0; i < tam3; i++) {
        Drawable* unElem = dynamicObjects.back();
        dynamicObjects.pop_back();

        delete unElem;
    }
    return quit;
}

bool MundoSBS::initLevel2(ClientSocket * client) {
//    cout << "INICIO NIVEL 2" << endl;

    //#NOTA: Lipio el buffer de datos del cliente.
    struct ObjectInit garbage;
    bool fin = false;
    while (!fin) {
        if (!player->tryPop(garbage)) {
            //no tengo elemento del nivel 1.
            fin = true;
        }
    }
    bool quit = false;
    bool zoomIn = false;
    bool zoomOut = false;
    struct NewPlayer myP;
    // print the number of sample chunk decoders available
    //    printf("There are %d sample chunk deocoders BEFORE available\n", Mix_GetNumChunkDecoders());
    //Stop the music
    Mix_HaltMusic();

    // print the number of sample chunk decoders available
    //    printf("There are %d sample chunk deocoders AFTER available\n", Mix_GetNumChunkDecoders());

    // halt playback on all channels
    //Mix_HaltChannel(-1);
    //The music that will be played
    Mix_Music *gMusic = NULL;
    //Musicalizacion de los eventos
    //  The sound effects that will be used
    Mix_Chunk *gHigh = NULL; // saltar
    Mix_Chunk *gLife = NULL; //bonus de vida o rayo

    //Para escribir Score y Lifes
    SDL_Texture* Message;
    SDL_Texture* Message2;
    SDL_Rect Message_rect; //create a rect
    SDL_Rect Message2_rect; //create a rect

    SDL_Texture* gameOverText;
    SDL_Rect gameOverRect;

    SDL_Renderer* gRenderer = NULL;
    SDL_Event event;
    string nameWindow = "SBS - ";
    nameWindow += vectorInputs.at(2)->getLabelText();

    gWindow = new Window(nameWindow, this->window.pxWidth, this->window.pxHeight, SDL_WINDOW_SHOWN, &gRenderer);
    if (!(gWindow->isInit())) {
        //        cout << "fallo el init" << endl;
        myLogFile->writeInLog(2, "[2] Error al cargar ventana de juego\n");
    } else {


        SBSImage* background = new SBSImage();

        if (TTF_Init()) {
            myLogFile->writeInLog(2, "[2] Ha ocurrido un error al cargar la imagen: ");
            myLogFile->writeInLog(2, TTF_GetError());
            myLogFile->writeInLog(2, "\n");
        }
        TTF_Font* Sans;
        Sans = TTF_OpenFont("Fonts/emulogic.ttf", 12); //this opens a font style and sets a size
        if (!Sans) {
            myLogFile->writeInLog(1, "[1] No se encontro la fuente\n");
        }
        if (SDL_Init(SDL_INIT_AUDIO) < 0) {
            printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        }
        if (!(background->loadMedia("Img/F3.png", &gRenderer))) {
            myLogFile->writeInLog(2, "[2] Error al cargar la imagen de fondo. \n");
        } else {
            //            cout << "Canales en uso: " << Mix_AllocateChannels(-1) << endl;
            //Initialize SDL_mixer
            if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) {
                printf("SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError());
            }
            //Load music
            gMusic = Mix_LoadMUS("Music/MarioSong.wav");
            if (gMusic == NULL) {
                printf("Failed to load beat music! SDL_mixer Error: %s\n", Mix_GetError());

            }

            //Load sound effects
            gHigh = Mix_LoadWAV("Music/smb_jump-super.wav");
            if (gHigh == NULL) {
                printf("Failed to load high sound effect! SDL_mixer Error: %s\n", Mix_GetError());

            }
            //            else cout << "Cargo bien el archivo de musiquita de saltar" << endl;

            gLife = Mix_LoadWAV("Music/smb_1-up.wav");
            if (gLife == NULL) {
                printf("Failed to load bonus sound effect! SDL_mixer Error: %s\n", Mix_GetError());

            }


            SBSImage* backgroundAntes = new SBSImage();
            backgroundAntes->loadMedia("Img/nivel2.png", &gRenderer);
            SDL_RenderClear(gRenderer);
            SDL_RenderCopy(gRenderer, backgroundAntes->getTexture(), NULL, NULL);
            SDL_RenderPresent(gRenderer);
            usleep(3000000);

            this->receiveLevelTwo(client);
            this->createFigures2(gRenderer);
            ScreenManager* screenManager = new ScreenManager(window.luWidth, window.luHeight, window.pxWidth, window.pxHeight, this->window.characterId);
            //
            /******************************************************************
             * CHARACTER
             ******************************************************************/
            Player* player = this->player;
            bool primeraVez = true;
            bool segundaVez = false;

            string sc = "Score: ";
            string lf = "Lifes: ";
            string go = "GAME OVER";

            usleep(50000); //
            player->runThreadRecv2();
            player->runThreadSend2();
            //
            SDL_Texture* mTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, background->getWidth(), background->getHeight());

            SDL_SetRenderDrawBlendMode(gRenderer, SDL_BLENDMODE_BLEND);
            SDL_SetTextureBlendMode(mTexture, SDL_BLENDMODE_BLEND);
            SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xAA, SDL_BLENDMODE_NONE);

            SDL_EventState(SDL_MOUSEMOTION, 0);

            // this is the color in rgb format, maxing out all would give you the color white, and it will be your text's color
            SDL_Color White = {255, 128, 0, 255};
            // as TTF_RenderText_Solid could only be used on SDL_Surface then you have to create the surface first    

            myLogFile->writeInLog(1, "[1] Se creo la pantalla transparente de Score&Life exitosamente. \n");
            if (Mix_PlayMusic(gMusic, -1) == -1) {
                printf("Mix_PlayMusic: %s\n", Mix_GetError());
                //                cout << "No pudo arrancar la musiquita" << endl;
            }
            //            cout << "No entro al if" << Mix_GetError() << endl;
            //Mix_PlayMusic(gMusic, -1);
            Mix_VolumeMusic(MIX_MAX_VOLUME / 2);
            //            printf("volume is now : %d\n", Mix_VolumeMusic(-1));
            while (!quit) {
                if (player->isInit()) {
                    SDL_SetRenderTarget(gRenderer, mTexture);
                    SDL_RenderClear(gRenderer);
                    SDL_RenderCopy(gRenderer, background->getTexture(), NULL, NULL);

                    struct Event e;
                    int sonar = 0;
                    //int sonarF = 0;
                    //                 if (SDL_PollEvent(&event)) {
                    if (event.key.state == SDL_PRESSED) {
                        e.released = NULL;
                        switch (event.key.keysym.sym) {
                            case SDLK_LEFT:
                                e.pressed = 'L';
                                break;
                            case SDLK_RIGHT:
                                e.pressed = 'R';
                                break;
                            case SDLK_UP:
                                e.pressed = 'U';
                                break;
                            case SDLK_DOWN:
                                e.pressed = 'D';
                                break;
                            case SDLK_SPACE:
                                e.pressed = 'B';
                                break;
                            default:
                                e.pressed = '@';
                                break;
                        }
                    } else {
                        if (event.key.state == SDL_RELEASED) {
                            e.pressed = NULL;
                            switch (event.key.keysym.sym) {
                                case SDLK_LEFT:
                                    e.released = 'L';
                                    break;
                                case SDLK_RIGHT:
                                    e.released = 'R';
                                    break;
                                case SDLK_UP:
                                    e.released = 'U';
                                    break;
                                case SDLK_DOWN:
                                    e.released = 'D';
                                    break;
                                default:
                                    e.released = '@';
                                    break;
                            }
                        } else {
                            e.released = NULL;
                            e.pressed = '@';
                        }
                    }
                    if (primeraVez) {
                        e. released = NULL;
                        e. pressed = 'D';

                    }
                    if (segundaVez) {
                        e. pressed = NULL;
                        e. released = 'D';
                        segundaVez = false;
                    }

//                    cout << "push eventtt" << endl;
                    player->pushEvent(e); //envio los datos 
                    bool end = false;
                    //CAMBIOS MAU
                    int cantidadActualizar = 0;
                    int cantidadPack = 50; //Se actualizara de a 50 paquetes
                    struct ObjectInit newData;

                    while (!end) {
                        while (cantidadActualizar <= cantidadPack) {//cantidad de paquetes a actualizar. para luego dibujar el ultimo
                            if (player->tryPop(newData)) {
                                /***********************************************
                                 * PASAR AL NIVEL 1
                                 ***********************************************/
//                                cout << "charace " << newData.idCharacter << " state " << newData.stateCharacter << " image " << newData.imageId << " objId " << newData.objectId << endl;
                                if (newData.level == 1) {

//                                    cout << newData.level << " " << newData.idCharacter << " " << newData.objectId << endl;
                                    end = true;
                                    quit = true;
                                    break;
                                }
                                if (newData.level == -1) {
//                                    cout << "IR A WAITING" << endl;
                                    this->waitingForReload = true;
                                    //                                    cout << newData.level << " " << newData.idCharacter << " " << newData.objectId << endl;

                                    end = true;
                                    quit = true;
                                    break;
                                }
                                if (newData.level == 3) {
//                                    cout << "Todos los players perdieron sus vidas" << endl;
                                    end = true;
                                    quit = true;
                                    this->setGameOver(true);
                                    break;
                                }
                                if (newData.level == 4) {
//                                    cout << "Game over + waiting" << endl;
                                    this->setGameOver(true);

                                    // DEBO ESPERAR AL LEVEL -1
                                    struct Event eventPulse;
                                    eventPulse.pressed = '@';

                                    bool stillWaiting = true;
                                    while (stillWaiting) {
                                        usleep(50000);
                                        player->pushEvent(eventPulse);

                                        struct ObjectInit obj;
                                        bool finished = this->player->tryPop(obj);

                                        if (finished) {
                                            if (obj.level == -1)
                                                stillWaiting = false;
                                        }

                                    }

                                    end = true;
                                    quit = true;
                                    this->waitingForReload = true;

                                    break;
                                }

                                if (!((newData.objectId == 0) && (newData.idCharacter == 0))) {
                                    if (newData.idCharacter < 30 || newData.idCharacter >= 0) {
                                        if (newData.idCharacter != ID_END_SEND) {
                                            
//                                            cout << "debe llegar"<<endl;
                                            this->updateDynamicObjects2(&newData, gRenderer);
                                            for (int j = 0; j < this->dynamicObjects2.size(); j++) {
//                                                                                                cout << "antes de actualize   " << this->dynamicObjects2.at(j)->getData().idCharacter << "   "<< this->dynamicObjects2.at(j)->getData().stateCharacter << endl;
                                                this->dynamicObjects2.at(j)->actualize();
//                                                                                                cout << "despues de actualize" << endl;
                                                //                                                cout << "this->dynamicObjects2.at(j)->getCharacterId()" << this->dynamicObjects2.at(j)->getData().idCharacter << endl;
                                                //                                                cout << "this->dynamicObjects2.at(j)->getData.objectId)" << this->dynamicObjects2.at(j)->getData().objectId << endl;

                                                //                                                if (this->dynamicObjects2.at(j)->getCharacterId() == screenManager->getCharacterId()) {
                                                //                                                if (!((this->dynamicObjects2.at(j)->getCharacterId() == 0) || (this->dynamicObjects2.at(j)->getData(). == 0))) {
                                                if (this->dynamicObjects2.at(j)->getData().idCharacter == screenManager->getCharacterId()) {
                                                    if (primeraVez) {
                                                        screenManager->setPosCamera(this->dynamicObjects2.at(j)->getPosX(), this->dynamicObjects2.at(j)->getPosY());
                                                        screenManager->actualizeSettings();
                                                        primeraVez = false;
                                                        segundaVez = true;
                                                    }
                                                    screenManager->setCharacterPos(this->dynamicObjects2.at(j)->getPosX(), this->dynamicObjects2.at(j)->getPosY());
                                                    screenManager->actualizeSettings();
                                                    //Score y Lifes
                                                    struct ObjectInit myObj;
                                                    sc = "Score: ";
                                                    myObj = this->dynamicObjects2.at(j)->getData();
                                                    sc.append(to_string(myObj.score));
                                                    lf = "Lifes: ";
                                                    lf.append(to_string(myObj.lifes));
                                                    if (myObj.stateCharacter == 12) {
                                                        screenManager->setObserver();
                                                        this->isObserver = true;
                                                    }
                                                }
                                                //                                                }
                                            }
                                            list<Drawable*> bulletList;
                                            for (int i = 0; i< this->bulletList.size(); i++) {
                                                Drawable* bullet = this->bulletList.at(i);
                                                if (bullet->getData().bulletStat != BULLET_DEAD) {
                                                    bullet->actualize();
                                                }
                                            }
                                            cantidadActualizar++;
                                        } else { //no se si este else es necesario. Lo dejo por las dudas :P
                                            //                                    end = true;
                                        }
                                    }
                                }
                            } else { //cuando size = 0. es necesario hacer un break. Para que el programa siga                                
                                break; // salfo de while interno.
                            }
                        }
                        end = true;
                    }
//                    cout << "staticsssss" << endl;
                    //Se actualizan todos los objetos estaticos
                    for (int j = 0; j < this->staticObjects2.size(); j++) {
                        this->staticObjects2.at(j)->actualize();
                    }

                    //Se dubujan todos los objetos estaticos
                    for (int j = 0; j < this->staticObjects2.size(); j++) {
                        this->staticObjects2.at(j)->draw();

                    }

                    if (!((newData.objectId == 0) && (newData.idCharacter == 0))) {
                        if (newData.idCharacter < 30) {
                            //Se dibujan todos los objetos dinamicos
                            for (int k = 0; k < this->dynamicObjects2.size(); k++) {
                                Drawable* elem = this->dynamicObjects2.at(k);
                                if (elem->getCharacterId() == screenManager->getCharacterId()) {
                                    if ((Mix_Playing(1) == 0) && (elem->getData().event.pressed == 'C')) {
                                        Mix_PlayChannel(1, gLife, 0);
                                        Mix_VolumeChunk(gLife, MIX_MAX_VOLUME);

                                    }
                                    if ((elem->getData().stateCharacter == 1) && (sonar == 0)) {
                                        if ((Mix_Playing(1) == 0) && (elem->getData().event.pressed == 'U')) {
                                            Mix_PlayChannel(1, gHigh, 0);
                                            Mix_VolumeChunk(gHigh, MIX_MAX_VOLUME);
                                            sonar++;
                                        }
                                    }
                                }
                                //                                cout << "Entro al dibujar de dinamicos" << endl;
                                //                                if (!((this->dynamicObjects2.at(k)->getData().idCharacter == 0) || (this->dynamicObjects2.at(k)->getData().idCharacter == 0))) {
                                if (elem->getData().imageId != -1) {
                                    elem->draw();
                                    //                                    }
                                }
                            }

                            //draw shoot
                            list<Drawable*> bulletList;
                            for (int i = 0; i< this->bulletList.size(); i++) {
                                Drawable* bullet = this->bulletList.at(i);
                                if (bullet->getData().bulletStat != BULLET_DEAD) {
                                    bullet->actualize();
                                    bullet->draw();
                                }
                            }
                        }
                    }

                    SDL_Surface* scoreMessage = TTF_RenderText_Solid(Sans, sc.c_str(), White);
                    SDL_Surface* livesMessage = TTF_RenderText_Solid(Sans, lf.c_str(), White);

                    int text_width = scoreMessage->w;
                    int text_height = scoreMessage->h;
                    Message = SDL_CreateTextureFromSurface(gRenderer, scoreMessage); //now you can convert it into a texture

                    int text_widthl = livesMessage->w;
                    int text_heightl = livesMessage->h;
                    Message2 = SDL_CreateTextureFromSurface(gRenderer, livesMessage); //now you can convert it into a texture

                    Message_rect.x = 0; //controls the rect's x coordinate
                    Message_rect.y = 0; // controls the rect's y coordinte
                    Message_rect.w = text_width; // controls the width of the rect
                    Message_rect.h = text_height; // controls the height of the rect

                    Message2_rect.x = 0; //controls the rect's x coordinate
                    Message2_rect.y = text_height + 5; // controls the rect's y coordinte
                    Message2_rect.w = text_widthl; // controls the width of the rect
                    Message2_rect.h = text_heightl; // controls the height of the rect



                    SDL_Surface* GOMessage = TTF_RenderText_Solid(Sans, go.c_str(), White);
                    int text_widthGO = GOMessage->w;
                    int text_heightGO = GOMessage->h;
                    gameOverText = SDL_CreateTextureFromSurface(gRenderer, GOMessage); //now you
                    gameOverRect.x = 200; //controls the rect's x coordinate
                    gameOverRect.y = 200; // controls the rect's y coordinte
                    gameOverRect.w = text_widthGO + 250; // controls the width of the rect
                    gameOverRect.h = text_heightGO + 50; // controls the height of the rect

                    SDL_SetRenderTarget(gRenderer, NULL);
                    screenManager->setZoom(zoomIn, zoomOut);
                    screenManager->actualizeSettings();
                    if (this->isObserver) {
                        screenManager->setObserver();
                    }
                    screenManager->draw(&gRenderer, &mTexture);

                    if (this->isObserver) {
                        SDL_RenderCopy(gRenderer, gameOverText, NULL, &gameOverRect);
                    } else {
                        SDL_RenderCopy(gRenderer, Message, NULL, &Message_rect);
                        SDL_RenderCopy(gRenderer, Message2, NULL, &Message2_rect);
                    }

                    SDL_FreeSurface(GOMessage);
                    GOMessage = NULL;
                    SDL_FreeSurface(scoreMessage);
                    scoreMessage = NULL;
                    SDL_FreeSurface(livesMessage);
                    livesMessage = NULL;

                    SDL_DestroyTexture(Message);
                    Message = NULL;
                    SDL_DestroyTexture(Message2);
                    Message2 = NULL;
                    //Fin Score y Lifes

                    SDL_RenderPresent(gRenderer);

                    if (SDL_PollEvent(&event)) {
                        checkQuitOrZoom(&event, &quit, &zoomIn, & zoomOut);
                    }

                } else {
                    //                    this->goodByePlayer();
                    quit = true;
                }
            }



            //Stop the music
            Mix_HaltMusic();
            delete screenManager;
            SDL_DestroyTexture(mTexture);
            mTexture = NULL;
            delete background;
        }
    }

    if (this->getGameOver()) {

        SBSImage* backgroundGO = new SBSImage();
        backgroundGO->loadMedia("Img/gameOver.png", &gRenderer);
        SDL_RenderClear(gRenderer);
        SDL_RenderCopy(gRenderer, backgroundGO->getTexture(), NULL, NULL);
        SDL_RenderPresent(gRenderer);
        if (SDL_PollEvent(&event)) {
            if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
                this->endMain = true;
            }
        }
        usleep(1000000);
        delete backgroundGO;

    } else if ((!this->salioManualmente) && (!this->getGameOver())) {
        bool salir = false;
        SBSImage* reinicio = new SBSImage();
        reinicio->loadMedia("Img/congratz.png", &gRenderer);
        SDL_RenderClear(gRenderer);
        SDL_RenderCopy(gRenderer, reinicio->getTexture(), NULL, NULL);
        SDL_RenderPresent(gRenderer);
        if (SDL_PollEvent(&event)) {
            if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
                salir = true;
                this->endMain = true;
            }
        }
        usleep(1000000);
        delete reinicio;
    }

    delete gWindow;
    SDL_DestroyRenderer(gRenderer);
    gRenderer = NULL;
    IMG_Quit();
    SDL_Quit();
    //Free the sound effects
    Mix_FreeChunk(gHigh);
    gHigh = NULL;
    Mix_FreeChunk(gLife);
    gLife = NULL;
    //Free the music
    Mix_FreeMusic(gMusic);
    gMusic = NULL;

    this->garbageCollector();
    Mix_CloseAudio();
    return quit;
}

void MundoSBS::updateDynamicObjects2(struct ObjectInit* obj, SDL_Renderer * renderer) {
    //    cout << "size: " << this->dynamicObjects2.size() << "UPDATE ubDyn: " << obj->ubicDyn << " new data  idCharacter:" << obj->idCharacter << " objId: " << obj->objectId << " level: " << obj->level << endl;
    if (obj->ubicDyn < this->dynamicObjects2.size() && obj->objectId != BULLET) {
        if (obj->idCharacter < 20 && obj->idCharacter > 10) {
            obj->rot = 0;
        }
        Drawable* elem = this->dynamicObjects2.at(obj->ubicDyn);
        //        cout << "updateeeeeeeeeeeeeeee " << endl;
        //        cout << "Size de objetos dinamicos: " << this->dynamicObjects2.size() << " obj->ubicDyn: " << obj->ubicDyn << " obj->idCharacter " << obj->idCharacter << " obj->objectId " << obj->objectId << endl;
        elem->updateData(*obj);
    } else {
        // se puede modificar el tamaño de los obj dynamicos sii se agrego un jugador        
        if ((obj->idCharacter != VACIO) && (obj->idCharacter < 5) && (obj->idCharacter > 0)) {
            if (obj->idCharacter > 0 && obj->idCharacter < 5) { // personajes 
                Character* character = new Character(obj->x, obj->y, &renderer, obj->idCharacter);
                this->dynamicObjects2.push_back(character);
                //                cout << "se agrega nuevo jugador con idCharacter: " << obj->idCharacter << endl;
            } else {
                if (obj->idCharacter == 11 || obj->idCharacter == 12) { //Enemigos
                    Enemy* enemy = new Enemy(obj->x, obj->y, &renderer, obj->idCharacter);
                    this->dynamicObjects2.push_back(enemy);
                } else {//boss
                    if (obj->idCharacter == 21) {
                        Boss* boss = new Boss(obj->x, obj->y, &renderer);
                        this->dynamicObjects2.push_back(boss);
                    }
                }
            }
        } else {
            if (obj->idCharacter == 11 || obj->idCharacter == 12) { //Enemigos
                Enemy* enemy = new Enemy(obj->x, obj->y, &renderer, obj->idCharacter);
                //                cout << "INSTANCIO UN ENEMY" << endl;
                this->dynamicObjects2.push_back(enemy);
            }
        }
        //parche para que me dibuje los enemigos.

        //objeto de tipo BULLET 
        if (obj->objectId == BULLET) { //bullet         
            //                        cout << "bullet" << endl;
            if (obj->bulletStat != BULLET_OLD && obj->bulletStat != BULLET_DEAD) { //es una bala nueva, agrego al vector para despues poder dibujar
                //add          
                //                cout << "Bulled NEW: " << obj->ubicDyn << endl;
                Object* object = new Object(*obj, renderer, obj->objectId, obj->imageId);
                this->bulletList.push_back(object);
            }
            //#NOTA: este if es para erreglar el error que se produce cuando se pierde un paquete. (Cambiar urgente)
            //update          
            //#NOTA: aveces pierdo un paquete y se va del rengo del vector, por lo tanto agrego una condicion mas el if 
            //para solucionar el problema, creo que el error se debe al envio de datos, aveces pierdo un flag de condicion.
            if (obj->bulletStat == BULLET_OLD && obj->ubicDyn == this->bulletList.size()) {
                //                cout << "Bulled NEW caso borde: " << obj->ubicDyn << endl;
                Object* object = new Object(*obj, renderer, obj->objectId, obj->imageId);
                this->bulletList.push_back(object);

            } else {//Bullet viejo (ya se encuentra en la lista)           
                //                cout << "bullet OLD ubicDyn: " << obj->ubicDyn << "  size: " << this->bulletList.size() << " stat:" << obj->bulletStat << endl;
                Drawable* elemBullet = this->bulletList.at(obj->ubicDyn);
                //                cout << "update" << endl;
                elemBullet->updateData(*obj);
            }
            if (obj->bulletStat == BULLET_DEAD) { //a eliminar, update para no dibujar
                //                cout << "Bulled DEAD" << endl;
                Drawable* elemBullet = this->bulletList.at(obj->ubicDyn);
                //                cout << "Bulled DEAD fin" << endl;
                elemBullet->updateData(*obj);
            }
        }
        //    }
    }
//            cout << "Size luego de updetear: " << this->dynamicObjects2.size() << endl;

}

void MundoSBS::updateDynamicObjects(struct ObjectInit* obj, SDL_Renderer * renderer) {


    //    cout << "size dynamicBodys" << this->dynamicObjects.size() << endl;
    //    cout << "size sssssssssssssstaticBodys" << this->staticObjects.size() << endl;

    if (obj->ubicDyn < this->dynamicObjects.size() && obj->objectId != BULLET) {
        if (obj->idCharacter < 20 && obj->idCharacter > 10) {
            obj->rot = 0;
        }
        Drawable* elem = this->dynamicObjects.at(obj->ubicDyn);
        elem->updateData(*obj);
        //        if (obj->idCharacter != 11) cout << elem->getData().event.pressed << endl;
    } else {
        // se puede modificar el tamaño de los obj dynamicos sii se agrego un jugador
        if ((obj->idCharacter != VACIO) && (obj->idCharacter < 5) && (obj->idCharacter > 0)) {
            Character* character = new Character(obj->x, obj->y, &renderer, obj->idCharacter);
            character->updateData(*obj);
            this->dynamicObjects.push_back(character);
//            cout << "se agrega nuevo jugador con idCharacter: " << obj->idCharacter << "  " << obj->ubicDyn << endl;
        }
        //objeto de tipo BULLET 
        if (obj->objectId == BULLET) { //bullet         
            if (obj->bulletStat != BULLET_OLD && obj->bulletStat != BULLET_DEAD) { //es una bala nueva, agrego al vector para despues poder dibujar
                //add          
                //                cout << "Bulled NEW: " << obj->ubicDyn << endl;
                Object* object = new Object(*obj, renderer, obj->objectId, obj->imageId);
                this->bulletList.push_back(object);
            }
            //#NOTA: este if es para erreglar el error que se produce cuando se pierde un paquete. (Cambiar urgente)
            //update          
            //#NOTA: aveces pierdo un paquete y se va del rengo del vector, por lo tanto agrego una condicion mas el if 
            //para solucionar el problema, creo que el error se debe al envio de datos, aveces pierdo un flag de condicion.
            if (obj->bulletStat == BULLET_OLD && obj->ubicDyn == this->bulletList.size()) {
                Object* object = new Object(*obj, renderer, obj->objectId, obj->imageId);
                this->bulletList.push_back(object);

            } else {//Bullet viejo (ya se encuentra en la lista)           
                //                cout << "bullet OLD ubicDyn: " << obj->ubicDyn << "  size: " << this->bulletList.size() << " stat:" << obj->bulletStat << endl;
                Drawable* elemBullet = this->bulletList.at(obj->ubicDyn);
                //                cout << "update " << endl;
                elemBullet->updateData(*obj);
            }
            if (obj->bulletStat == BULLET_DEAD) { //a eliminar, update para no dibujar
                //                cout << "Bulled DEAD" << endl;

                Drawable* elemBullet = this->bulletList.at(obj->ubicDyn);
                elemBullet->updateData(*obj);
            }
        }
    }
}

int MundoSBS::recv(ClientSocket* client, void *buf, int len) {
    int timeOut = 10; //seg      
    int n = client->recvTimeOut(buf, len, timeOut);

    if (n == -1) {
        //        cout << "#ERROR-LOG:Error recv" << endl;
        myLogFile->writeInLog(2, "[2] Error interno del socket al recibir evento del server.\n");
        //        exit(1);
    }
    if (n == -2) {
        myLogFile->writeInLog(2, "[2] El server se desconecto mientras se recibía la info de la pantalla. Se cerrará la ejecución\n");
        //        cout << "#ERROR-LOG:El temporizador vencio" << endl;
        //        this->setInit(false);
        //        exit(1);
    }
    if (n == 0) {

        myLogFile->writeInLog(2, "[2] El server se desconecto mientras se recibía la info de la pantalla. Se cerrará la ejecución\n");
        //        cout << "#ERROR-LOG: Se fue el servidor" << endl;
        //        this->setInit(false);
        exit(1);
    }

    return n;
}

void MundoSBS::recvNextPlayer(ClientSocket * client) {
    struct NewPlayer player;
    int len = sizeof (player);

    int n = this->recv(client, &player, len);

    if (n != 0 && n != -1 && n != -2) {
        if (player.characterId != window.characterId) { // no soy yo mismo
            //                            cout << "recv player: " << player.characterId << " " << player.nombre << endl;

            this->allPlayers.push_back(player);
        }
    }

}

bool MundoSBS::waitingForServer(ClientSocket* client) {
    bool quit = false;
    bool stillWaiting = true;
    Window* myWindow;
    SDL_Event event;

    myWindow = new Window("SBS - Cliente", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN, &gRenderer);
    this->gWindow = myWindow;
    SBSImage* backWaiting = new SBSImage();

    if (!(gWindow->isInit())) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la ventana de SDL.\n");
    } else if (TTF_Init() == -1) {
        myLogFile->writeInLog(2, "[2] Fallo al inicializar la fuente de SDL.n");
    } else {

        if (!(backWaiting->loadMedia("Img/waitingPlayers.png", &gRenderer))) {
            myLogFile->writeInLog(1, "[1] Error al cargar la imagen de fondo.\n");
            backWaiting->loadMedia(SCREEN_BACKGROUND, &gRenderer);
        }
        if (!loadLabels()) {
            myLogFile->writeInLog(1, "[1] Error al cargar labels. \n");
        }

        struct Event eventPulse;
        int lenPulse = sizeof (eventPulse);
        eventPulse.pressed = '@';

        while (stillWaiting) {
            usleep(50000);

            client->sendAll(&eventPulse, lenPulse);

            if (!quit) {
                if (SDL_PollEvent(&event)) {
                    if ((event.type == SDL_QUIT) || (event.key.keysym.sym == SDLK_ESCAPE)) {
                        quit = true;
                        stillWaiting = false;
                    }
                }
                SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
                SDL_RenderClear(gRenderer);
                SDL_RenderCopy(gRenderer, backWaiting->getTexture(), NULL, NULL);
                labelWaiting->renderLabel(&gRenderer, 10, 570);
                //Update screen
                SDL_RenderPresent(gRenderer);
            }

            struct ObjectInit obj;
            int len = sizeof (obj);
            int n = this->recv(client, &obj, len);
            // espero el flag de fin de espera (level -1)
            if (n != 0 && n != -1 && n != -2) {
                if (obj.level == -1) {
                    stillWaiting = false;
                    quit = true;
                }
            }

        }

        //Disable text input
        SDL_StopTextInput();
        delete backWaiting;
        delete myWindow;
        SDL_DestroyRenderer(gRenderer);
        gRenderer = NULL;
        IMG_Quit();
        SDL_Quit();
        return quit;
    }

    return quit;
}

bool MundoSBS::startGame(ClientSocket* client) {

    // si estoy comenzando en un nivel reiniciado
    if (this->window.reloadLevel != 0) {
        return this->waitingForServer(client);
    }

    if (this->allPlayers.empty()) {
        return false;
    } else if (this->allPlayers.size() == this->window.maxPlayers) {
        return true;
    } else {
        return false;
    }
}

bool MundoSBS::end() {
    return this->endMain;
}

void MundoSBS::garbageCollector() {
//    cout << "GARBAGE COLLECTOR" << endl;

    //limpia vector de balas
    int tamBullet = this->bulletList.size();
    for (int i = 0; i < tamBullet; i++) {
        Drawable* unElem = this->bulletList.at(i);
        delete unElem;
    }
    int tamBullet2 = this->bulletList.size();
    for (int i = 0; i < tamBullet2; i++) {
        this->bulletList.pop_back();
    }

    //limpia vector de estaticos de nivel 1
    int tamStatic = this->staticObjects.size();
    for (int i = 0; i < tamStatic; i++) {
        Drawable* unElem = this->staticObjects.at(i);
        delete unElem;
    }
    int tamStatic2 = this->staticObjects.size();
    for (int i = 0; i < tamStatic2; i++) {
        this->staticObjects.pop_back();
    }

    //limpia vector de dinamicos de nivel 1
    int tamDynamic = this->dynamicObjects.size();
    for (int i = 0; i < tamDynamic; i++) {
        Drawable* unElem = this->dynamicObjects.at(i);
        delete unElem;
    }
    int tamDynamic2 = this->dynamicObjects.size();
    for (int i = 0; i < tamDynamic2; i++) {
        this->dynamicObjects.pop_back();
    }

    //limpia vector de estaticos de nivel 2
    int tamStatic21 = this->staticObjects2.size();
    for (int i = 0; i < tamStatic21; i++) {
        Drawable* unElem = this->staticObjects2.at(i);
        delete unElem;
    }
    int tamStatic22 = this->staticObjects2.size();
    for (int i = 0; i < tamStatic22; i++) {
        this->staticObjects2.pop_back();
    }

    //limpia vector de dinamicos de nivel 2
    int tamDynamic21 = this->dynamicObjects2.size();
    for (int i = 0; i < tamDynamic21; i++) {
        Drawable* unElem = this->dynamicObjects2.at(i);
        delete unElem;
    }
    int tamDynamic22 = this->dynamicObjects2.size();
    for (int i = 0; i < tamDynamic22; i++) {
        this->dynamicObjects2.pop_back();
    }
}

void MundoSBS::setGameOver(bool flag) {
    this->gameOver = flag;
}

bool MundoSBS::getGameOver() {
    return this->gameOver;
}
